多態
指的是一個引用型別
使用super class
,但是contructor
(構造器)使用sub class
多態只著重在方法
的部分,屬性
是沒有多態
的。
也可以稱做sub class
物件的多態性。
class Person {
String name;
public void eat() {
System.out.println("Person need eat.");
}
}
class Man extends Person {
// method override
public void eat() {
System.out.println("Man eat a lots of meat");
}
}
public class PersonTest {
public static void main(String[] args) {
// sub class object多態性
Person person = new Man();
person.eat(); // Man eat a lots of meat
}
}
super class
: Person
sub class
: Man
Person person = new Man();
編譯時會認為person
的方法是看Person
class
,但是當實際調用時會調用Man
class
中的方法。
super class
& sub class
override
)當使用多態性
的方式去宣告一個物件時,不能使用一般的方式去使用在sub class
中所宣告特有
的屬性
或方法
。
使用強制類型轉換
的方式,可以讓使用多態
的sub class
調用sub class
中特有的屬性
或方法
。
例如:
class Person {
String name;
public void eat() {
System.out.println("Person need eat.");
}
}
class Man extends Person {
double height;
// method override
public void eat() {
System.out.println("Man eat a lots of meat");
}
public void drink() {
System.out.println("Man drink water");
}
}
class Child extends Person {
}
public class PersonTest {
public static void main(String[] args) {
// sub class object多態性
Person person = new Man();
person.eat(); // Man eat a lots of meat
// 會錯誤
// person.height;
// person.drink();
Man man = (Man) person;
//可以正常使用
person.height;
person.drink();
Person person1 = new Child();
Man child = (Man) person1;
// 會錯誤 ClassCastException
// child.height;
// child.drink();
}
}
這邊可以看到有2個地方註釋起來並寫上會錯誤
person.height
:
類型
宣告為Person
了,所以是無法直接去使用在Man
中宣告的屬性
和方法
。強制類型轉換
的方式去將person
轉換並賦值,如上面的Man man = (Man) person;
。person
紀錄的是一個在Heap
中的位址值
,所以當這樣宣告時,man
所存的值也是和person
紀錄相同的位址值
。(之前在陣列
中有提到過,如果賦值的是非
基本數據類型時,都只是記錄存放在Heap
中的位址值
,當Heap
中的值更改時,因為變數的值
都是指向同一個地方,不管使用哪一個變數去查值時,結果都是去找該位址值中的值)child.height
:
Person
是Man
的super class
,所以它不會出現錯誤。Man
和Child
沒有任何關係,所以會出現ClassCastException
(類型轉換異常)。如果要在這樣的情況下去使用時,建議使用instanceof
先進行判斷,確定沒問題了再去做強制類型轉換的動作。
class Person {
String name;
public void eat() {
System.out.println("Person need eat.");
}
}
class Man extends Person {
double height;
// method override
public void eat() {
System.out.println("Man eat a lots of meat");
}
public void drink() {
System.out.println("Man drink water");
}
}
class Child extends Person {
}
public class PersonTest {
public static void main(String[] args) {
// sub class object多態性
Person person = new Man();
person.eat(); // Man eat a lots of meat
// 會錯誤
// person.height;
// person.drink();
if(person instanceof Man) {
Man man = (Man) person;
//可以正常使用
person.height;
person.drink();
}
Person person1 = new Child();
if(person1 instanceof Child) {
// 報錯
// Man child = (Man) person1;
}
// Always false, because person1 is neither an instance of the Man class nor an
// instance of its subclasses.
if(person1 instanceof Man) {
Man child = (Man) person1;
}
if(person1 instanceof Child) {
Child child = (Child) person1;
System.out.println("我成功轉換了") //我成功轉換了
}
}
}
💡 "a instanceof b":指的是問 "a" 是否為 "b" 的 "sub class",會返回一個 "true" 或 "false"。
💡
"a instanceof b" > "true"
"a instanceof superb" > "true"
"b is superb's sub class"
class Transportation {
public void speed() {
System.out.println("transpertation speed.");
}
}
class Train extends Transportation {
public void speed() {
System.out.println("The train speed is 60 kilometers");
}
}
class HighSpeedRail extends Transportation {
public void speed() {
System.out.println("The HighSpeedRail speed is 260 kilometers");
}
}
public class TransportationTest {
public static void main(String[] args) {
TransportationTest test = new TransportationTest();
Transportation train = new Train();
Transportation highSpeedRail= new HighSpeedRail();
test.currentSpeed(train); //The train speed is 60 kilometers
test.currentSpeed(highSpeedRail); //The HighSpeedRail speed is 260 kilometers
}
public void currentSpeed(Transportation transportation) {
transportation.speed();
}
}
當使用多態性
時,可以使擴充性
更好,例如public void currentSpeed(Transportation transportation)
,由於使用多態性
的關係,Java會自動去找尋對應的sub class
中,是否有重寫的方法,若沒有則會去調用super class
中的方法,並且這樣的方式也可以減少很多重複的程式碼。
例如:沒有使用多態性的情況
public class TransportationTest {
public static void main(String[] args) {
TransportationTest test = new TransportationTest();
Train train = new Train();
HighSpeedRail highSpeedRail= new HighSpeedRail();
test.currentSpeed(train); //The train speed is 60 kilometers
test.currentSpeed(highSpeedRail); //The HighSpeedRail speed is 260 kilometers
}
public void currentSpeed(Train train) {
train.speed();
}
public void currentSpeed(HighSpeedRail highSpeedRail) {
highSpeedRail.speed();
}
}
必須要依照不同的類別去寫不同的方法,由於範例中只有兩個sub class
,所以看起好像有點雞肋,但是當sub class
多了起來後,使用多態性
的好處和優點就能夠漸漸浮現出來,並且當有新增的sub class
時,也不必再特別為了這個sub class
增加新的方法。
instanceOf 這段程式碼是不是錯了:
// always false, because person1 not Child sub class
if(person1 instanceOf Child) {
Man child = (Man) person1;
}
因為
Person person1 = new Child();
所以
if(person1 instanceOf Child) 會是 true
那這段是不是原本應該是:
// always false, because person1 not Child sub class
if(person1 instanceOf Man) {
Man child = (Man) person1;
}
magread
你好,第一段確實有誤,應該會是true
,感謝你的回覆。
if(person1 instanceof Child) {
// 報錯
// Man child = (Man) person1;
}
第二段可以這麼說,但是註解可能也要換一下就會符合我想表達的XD,這邊比較想要表達的是雖然Man
和Child
都是繼承Person
,但他們彼此間沒有任何關係。// Always false, because person1 is neither an instance of the Man class nor an instance of its subclasses.
我有把這段補上去了,謝謝你~~
另外instanceof
的o
是小寫,我寫錯了,謝謝你讓我發現這個錯誤XD
錯誤的部分已修正~